package aimis.controller;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import aimis.constant.ResponseEnum;
import aimis.domain.Department;
import aimis.dto.PageQuery;
import aimis.dto.Result;
import aimis.dto.TableList;
import aimis.dto.form.DepartmentForm;
import aimis.repo.DepartmentRepo;

import java.util.List;

@RestController
public class DepartmentController {
    @Autowired
    private DepartmentRepo departmentRepo;

    @PostMapping("/department/add")
    public Result add(@RequestBody @Validated(DepartmentForm.AddDepartment.class) DepartmentForm departmentForm) {
        var parent = departmentRepo.findById(departmentForm.getParentId()).orElse(null);
        Department root;
        if (parent == null) {
            root = null;
        } else {
            root = parent.getRoot();
        }
        Department departmentByParentAndNameAndRoot = departmentRepo.getDepartmentByParentAndNameAndRoot(parent, departmentForm.getName(), root);
        if (departmentByParentAndNameAndRoot != null) {
            return Result.error(ResponseEnum.DEPARTMENT_REPEAT);
        }
        //Form对象-》Domain对象
        Department department = new Department();
//        department.setSort(departmentForm.getSort());
//        department.setName(departmentForm.getName());
        BeanUtils.copyProperties(departmentForm, department);
        if (departmentForm.getParentId() == null) {
            department.setParent(null);
        } else {
            department.setParent(parent);
        }

        departmentRepo.save(department);
        //更新root
        if (department.getParent() != null) {
            department.setRoot(department.getParent().getRoot());
        } else {
            department.setRoot(department);
        }
        departmentRepo.save(department);
        return Result.success(ResponseEnum.OK);
    }

    @PostMapping("/department/edit")
    public Result edit(@RequestBody @Validated(DepartmentForm.EditDepartment.class) DepartmentForm departmentForm) {
        //Form对象-》Domain对象
        var findOne = departmentRepo.findById(departmentForm.getId());
        var department = findOne.get();
        BeanUtils.copyProperties(departmentForm, department);
        if (departmentForm.getParentId() == null) {
            department.setParent(null);
        } else {
            var parent = departmentRepo.findById(departmentForm.getParentId());
            department.setParent(parent.get());
        }
        departmentRepo.save(department);
        //更新root
        if (department.getParent() != null) {
            department.setRoot(department.getParent().getRoot());
        } else {
            department.setRoot(department);
        }
        return Result.success(ResponseEnum.OK);


    }

    @PostMapping("/department/get")
    public Result get(Long id) {
        var department = departmentRepo.findById(id);
        if (department.isPresent()) {
            return Result.success(ResponseEnum.OK).add("department", department);
        } else {
            return Result.error(ResponseEnum.DATA_NOT_EXIST);
        }
    }

    @PostMapping("/department/delete")
    public Result delete(@RequestBody @Validated(DepartmentForm.DeleteDepartment.class) DepartmentForm departmentForm) {
        //Form对象-》Domain对象
        var findOne = departmentRepo.findById(departmentForm.getId());
        departmentRepo.deleteById(departmentForm.getId());
        return Result.success(ResponseEnum.OK);
    }

    @PostMapping(value = "/department/findByQuery")
    public TableList<Department> findByQuery(String name, @RequestHeader(value = "departmentId") Long departmentId, PageQuery pageQuery) {
        var pageable = pageQuery.toPageable();
        if (name != null && name.isBlank())
            name = null;

        var root = departmentRepo.findById(departmentId).get().getRoot();
        if (root.getAccessAllDepartment()) {
            var departments = departmentRepo.findByQuery(name, pageable);
            return TableList.create(departments);
        } else {
            var departments = departmentRepo.findByQuery(name, root, pageable);
            return TableList.create(departments);
        }
    }

    //@PreAuthorize("hasAnyAuthority('查询所有department')")
    @PostMapping(value = "/department/findAll")
    public List<Department> findAll(@RequestHeader(value = "departmentId") Long departmentId) {
        var root = departmentRepo.findById(departmentId).get().getRoot();
        if (root.getAccessAllDepartment())
            return departmentRepo.findAll();
        else {
            return departmentRepo.findByRoot(root);
        }
    }

    @PostMapping(value = "/department/getDepartmentTree")
    public List<Department> getDepartmentTree(Long parentId) {
        return departmentRepo.findByParentId(parentId);
    }

    @PostMapping(value = "/department/getAllRootDepartment")
    public TableList<Department> getAllRootDepartment(@RequestHeader(value = "departmentId") Long departmentId, PageQuery pageQuery) {
        var pageable = pageQuery.toPageable();
        var root = departmentRepo.findById(departmentId).get().getRoot();
        if (root.getAccessAllDepartment()) {
            return TableList.create(departmentRepo.getAllRootDepartment(pageable));
        } else {
            return TableList.create(departmentRepo.getAllRootDepartment(root, pageable));
        }
    }

    @PostMapping(value = "/department/getAllRootDepartmentList")
    public List<Department> getAllRootDepartment(@RequestHeader(value = "departmentId") Long departmentId) {
        var root = departmentRepo.findById(departmentId).get().getRoot();
        if (root.getAccessAllDepartment())
            return departmentRepo.getAllRootDepartment();
        else
            return departmentRepo.getAllRootDepartment(root);
    }

    /**
     * 设置该部门（包含父部门和子部门）是否可以访问全部数据
     *
     * @param id
     * @param flag false不能访问，true可以访问
     * @return
     */
    @PostMapping("/department/accessAllDepartment")
    public Result accessAllDepartment(Long id, Boolean flag) {
        var find = departmentRepo.findById(id);
        var root = find.get().getRoot();
        accessAllDepartment(root, flag);
        return Result.success();
    }

    private void accessAllDepartment(Department root, Boolean flag) {
        root.setAccessAllDepartment(flag);
        departmentRepo.save(root);
        for (var c : root.getChildren()) {
            accessAllDepartment(c, flag);
        }
    }
}
